﻿using System;
using System.Data.Odbc;

namespace Centido.Core
{
    /// <summary>
    ///   A set of table contains operations.
    /// </summary>
    public static class TableContainsOperations
    {
        /// <summary>
        ///   Checks whether the target data source contains a row with the specified id.
        /// </summary>
        /// <param name="table">The target table.</param>
        /// <param name = "rowId">The id of the row.</param>
        /// <param name = "source">The target data source.</param>
        /// <returns>Returns true if the target data source contains a row with the specifed id; otherwise, false.</returns>
        private static bool ContainsRowImplementation(Table table, Guid rowId, DataSource source)
        {
            var tableName = table.GetDataSourceName(source);

            var rowWasFound = false;

            table.Domain.DbAccess.ExecuteScalar(
                cmd =>
                {
                    cmd.CommandText = string.Format(
                        "select 1 from {0} where {1}=?",
                        tableName,
                        Db.Tables.UserTable.Col.Id);

                    cmd.Parameters.Add(table.Domain.DbAccess.CreateParameter("id",
                        OdbcType.Binary, rowId.ToByteArray()));
                },
                result => rowWasFound = DbValue.GetInteger(result) == 1);

            return rowWasFound;
        }


        /// <summary>
        ///   Checks whether the table contains a row with the specified id.   
        /// </summary>
        /// <remarks>
        /// <para>The current user has to have the select permission on this table in order to execute this function/</para>
        /// </remarks>
        ///<param name="table">The target table.</param>
        ///<param name = "rowId">The id of the requested row.</param>
        /// <exception cref="System.Data.Common.DbException">Thrown when the current user has no select permission on the table.</exception>
        /// <returns>True if the table contains a row with the specified id; otherwise, false.</returns>
        /// <example>
        ///   The following example shows how to check that the table contains a row with the specified id.
        /// <code>
        ///     using System;
        ///     using Centido.Core;
        /// 
        ///     class Sample
        ///     {
        ///         static void Main()
        ///         {
        ///             var domainConfig = new DomainConfiguration()
        ///             {
        ///                 DbConnectionString = @"Driver={SQL Server};Server=.\SQLEXPRESS;Database=MyDb;Uid=admin;Pwd=P@ssw0rd;",
        ///                 DbProviderName = "MSSQLSERVER"
        ///             };
        ///         
        ///             var domain = Domain.Build(domainConfig);
        ///             
        ///             domain.DeleteAll();
        ///             
        ///             //Creating a new table
        ///             var table = domain.AddTable("my_table");
        /// 
        ///             //Granting all necessary permissions
        ///             table.GrantAll();
        ///
        ///             //Inserting a row
        ///             Console.WriteLine("Inserting a row");
        /// 
        ///             var id = table.InsertRow();
        /// 
        ///             //Checking existence of the row
        ///             if (table.ContainsRow(id))
        ///                 Console.WriteLine("The table contains a row with id = {0}", id);    
        ///             else
        ///                 Console.WriteLine("The table doesn't contain a row with id = {0}", id);
        /// 
        ///             //Deleting the row
        ///             Console.WriteLine("Deleting the row");
        /// 
        ///             table.DeleteRow(id);
        /// 
        ///             //Checking existence of the row
        ///             if (table.ContainsRow(id))
        ///                 Console.WriteLine("The table contains a row with id = {0}", id);    
        ///             else
        ///                 Console.WriteLine("The table doesn't contain a row with id = {0}", id);
        ///         }
        ///     }
        /// </code>
        /// </example>
        public static bool ContainsRow(this Table table, Guid rowId)
        {
            if (table == null)
                throw new ArgumentNullException("table");

            return ContainsRowImplementation(table, rowId, DataSource.UserView);
        }


        /// <summary>
        ///   Checks whether the specified data source contains a row with the specified id.
        /// </summary>
        /// <remarks>
        /// <para>The current user has to have the select permission on the specified data source.</para>
        /// </remarks>
        ///<param name="table">The target table.</param>
        ///<param name = "rowId">The id of the requested row.</param>
        /// <param name = "source">The data source.</param>
        /// <exception cref="System.Data.Common.DbException">Thrown when the current user has no permission on the specified data source.</exception>
        /// <returns>True if the specified data source contains a row with the specified id; otherwise, false.</returns>
        /// <example>
        ///     The following example shows how to check that the internal table contains a row with the specified id.
        /// <code>
        ///     using System;
        ///     using Centido.Core;
        /// 
        ///     class Sample
        ///     {
        ///         static void Main()
        ///         {
        ///             var domainConfig = new DomainConfiguration()
        ///             {
        ///                 DbConnectionString = @"Driver={SQL Server};Server=.\SQLEXPRESS;Database=MyDb;Uid=admin;Pwd=P@ssw0rd;",
        ///                 DbProviderName = "MSSQLSERVER"
        ///             };
        ///         
        ///             var domain = Domain.Build(domainConfig);
        ///             
        ///             domain.DeleteAll();
        ///             
        ///             //Creating a new table
        ///             var table = domain.AddTable("my_table");
        /// 
        ///             //Granting all necessary permissions
        ///             table.GrantAll();
        ///
        ///             //Inserting a row
        ///             Console.WriteLine("Inserting a row");
        /// 
        ///             var id = table.InsertRow();
        /// 
        ///             //Checking existence of the row
        ///             if (table.ContainsRow(id))
        ///                 Console.WriteLine("The internal table contains a row with id = {0}", id);    
        ///             else
        ///                 Console.WriteLine("The internal table doesn't contain a row with id = {0}", id);
        /// 
        ///             //Deleting the row
        ///             Console.WriteLine("Deleting the row");
        /// 
        ///             table.DeleteRow(id);
        /// 
        ///             //Checking existence of the row
        ///             if (table.ContainsRow(id))
        ///                 Console.WriteLine("The internal table contains a row with id = {0}", id);    
        ///             else
        ///                 Console.WriteLine("The internal table doesn't contain a row with id = {0}", id);
        ///         }
        ///     }   
        /// </code>
        /// </example>
        public static bool ContainsRow(this Table table, Guid rowId, DataSource source)
        {
            if (table == null)
                throw new ArgumentNullException("table");

            return ContainsRowImplementation(table, rowId, source);
        }
    }
}
